/*
 * Copyright (c) 2023-2023 elsfs Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.elsfs.cloud.common.security.authentication;

import java.util.Collection;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.elsfs.cloud.api.security.service.SecurityUserService;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtClaimNames;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;

/**
 * 携带userid的 AbstractAuthenticationToken 用于 资源服务器的转换 <code>
 * http
 * .oauth2ResourceServer((oauth2) -> oauth2
 * .jwt(jwtConfigurer->
 * jwtConfigurer.
 * jwtAuthenticationConverter(new JwtUserIdAuthenticationConverter(elsfsUserDetailsService))
 * )
 * );
 * </code>
 *
 * @author zeng
 * @see OAuth2ResourceServerConfigurer.JwtConfigurer#jwtAuthenticationConverter(Converter)
 */
@Setter
@Slf4j
@RequiredArgsConstructor
public class JwtUserIdAuthenticationConverter
    implements Converter<Jwt, AbstractAuthenticationToken> {
  private Converter<Jwt, Collection<GrantedAuthority>> jwtGrantedAuthoritiesConverter =
      new JwtGrantedAuthoritiesConverter();
  private final SecurityUserService securityUserService;
  private String principalClaimName = JwtClaimNames.SUB;

  @Override
  public final AbstractAuthenticationToken convert(Jwt jwt) {
    // 转换权限
    //    Collection<GrantedAuthority> authorities =
    // this.jwtGrantedAuthoritiesConverter.convert(jwt);
    // 获取用户名
    String principalClaimValue = jwt.getClaimAsString(this.principalClaimName);
    var user = securityUserService.loadUserByUsername(principalClaimValue);
    return UsernamePasswordAuthenticationToken.authenticated(user, null, user.getAuthorities());
  }
}
